/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights
 * reserved. <a>http://www.cqcis.com</a>
 */
package com.cqcis.uip.base.framework.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.StringTokenizer;

import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.osgi.framework.Bundle;

/**
 * @author huangmy
 * @date   2008-4-6
 */
public class TelnetCommandInterpreter implements CommandInterpreter {
	private static final String WS_DELIM = " \t\n\r\f";
	private StringTokenizer tok;
	private CommandProvider[] commandProviders; // 命令服务	
	private String newline = "\r\n";
	private StringBuffer msgBuf;
	
	public TelnetCommandInterpreter(String cmdline, CommandProvider[] commandProviders, StringBuffer msgBuf) {
		tok = new StringTokenizer(cmdline);
		this.commandProviders = commandProviders;
		this.msgBuf = msgBuf;
	}
	
	public String nextArgument() {
		if (tok == null || !tok.hasMoreElements())
			return null;
		
		String arg = tok.nextToken();
		if (arg.startsWith("\"")) {
			if (arg.endsWith("\"")) {
				if (arg.length() >= 2)
					// strip the beginning and ending quotes
					return arg.substring(1, arg.length() - 1);
			}
			String remainingArg = tok.nextToken("\"");
			arg = arg.substring(1) + remainingArg;
			// skip to next whitespace separated token
			tok.nextToken(WS_DELIM);
		} else if (arg.startsWith("'")) {
			if (arg.endsWith("'")) {
				if (arg.length() >= 2)
					// strip the beginning and ending quotes
					return arg.substring(1, arg.length() - 1);
			}
			String remainingArg = tok.nextToken("'");
			arg = arg.substring(1) + remainingArg;
			// skip to next whitespace separated token
			tok.nextToken(WS_DELIM);
		}
		
		return arg;
	}

	@SuppressWarnings("unchecked")
	public Object execute(String cmd) {
		Object retval = null;
		Class[] parameterTypes = new Class[] {CommandInterpreter.class};
		Object[] parameters = new Object[] {this};
		boolean executed = false;
		int size = commandProviders.length;
		for (int i = 0; !executed && (i < size); i++) {
			try {
				Object target = commandProviders[i];
				Method method = target.getClass().getMethod("_" + cmd, parameterTypes); //$NON-NLS-1$
				retval = method.invoke(target, parameters);
				executed = true; // stop after the command has been found
			} catch (NoSuchMethodException ite) {
				// keep going - maybe another command provider will be able to execute this command
			} catch (InvocationTargetException ite) {
				executed = true; // don't want to keep trying - we found the method but got an error
				printStackTrace(ite.getTargetException());
			} catch (Exception ee) {
				executed = true; // don't want to keep trying - we got an error we don't understand
				printStackTrace(ee);
			}
		}
		// if no command was found to execute, display help for all registered command providers
		if (!executed) {			
			for (int i = 0; i < size; i++) {
				try {
					CommandProvider commandProvider = (CommandProvider) commandProviders[i];
					print(commandProvider.getHelp());					
				} catch (Exception ee) {
					printStackTrace(ee);
				}
			}			
		}
		
		return retval;
	}

	public void print(Object o) {
		msgBuf.append(o);
	}

	public void println() {
		println("");
	}

	public void println(Object o) {
		print(o + newline);
	}

	public void printStackTrace(Throwable t) {
		StringWriter sw = new StringWriter();
		t.printStackTrace(new PrintWriter(sw));
		println(sw.toString());
	}

	@SuppressWarnings("unchecked")
	public void printDictionary(Dictionary dic, String title) {
		if (dic == null)
			return;

		int count = dic.size();
		String[] keys = new String[count];
		Enumeration keysEnum = dic.keys();
		int i = 0;
		while (keysEnum.hasMoreElements()) {
			keys[i++] = (String) keysEnum.nextElement();
		}
		
		if (title != null) {
			println(title);
		}
		for (i = 0; i < count; i++) {
			println(" " + keys[i] + " = " + dic.get(keys[i])); 
		}
		println();
	}

	public void printBundleResource(Bundle bundle, String resource) {
		URL entry = null;
		entry = bundle.getEntry(resource);
		if (entry != null) {
			try {
				println(resource);
				InputStream in = entry.openStream();
				byte[] buffer = new byte[1024];
				int read = 0;
				try {
					while ((read = in.read(buffer)) != -1)
						print(new String(buffer, 0, read));
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) {
						}
					}
				}
			} catch (Exception e) {
				printStackTrace(e);
			}
		} else {
			println("console resource not in bundle."); 
		}
	}
}
